package com.enlorenz.core.exception;

import java.util.Date;
import java.util.List;

import com.enlorenz.common.util.DataDetUtils;
import com.enlorenz.core.exception.common.ElzExceptionUtil;

/**
 * Elz基础异常
 * 用于同一异常额模式
 * 必须包含系统名，以及异常代码
 * @author lcb
 */
public class ElzBaseException extends RuntimeException{
	private static final long serialVersionUID = 1L;
	//系统名称
	private String sysName;
	//附加信息
	private String extendInfo;
	//异常代码
	private ElzExpCode expCode;
	//发生时间
	private Date occurredTime=new Date();
	
	
	/**
	 * 实例化Elz异常
	 * @param sysName 系统名
     * @param expCode 异常代码
     * @param msg 异常信息
     * @param args 异常信息参数
	 */
    public ElzBaseException(String sysName,ElzExpCode expCode)
    {
    	super(formatExpMsg(sysName, expCode,""));
    	this.sysName=sysName;
    	this.expCode=expCode;
    }
	
	/**
	 * 实例化Elz异常
	 * @param sysName 系统名
     * @param expCode 异常代码
     * @param msg 异常信息
     * @param args 异常信息参数
	 */
    public ElzBaseException(String sysName,ElzExpCode expCode,String msg,Object ... args)
    {
    	super(formatExpMsg(sysName, expCode, formatMsg(msg, args)));
    	this.sysName=sysName;
    	this.expCode=expCode;
    	this.extendInfo=formatMsg(msg, args);
    }

    /**
     * 实例化Elz异常
     * @param throwable 父异常
	 * @param sysName 系统名
     * @param expCode 异常代码
     * @param msg 异常信息
     * @param args 异常信息参数
     */
    public ElzBaseException(Throwable throwable,String sysName,ElzExpCode expCode,String msg,Object ... args)
    {
    	super(formatExpMsg(sysName, expCode, formatMsg(msg, args)), throwable);
    	this.sysName=sysName;
    	this.expCode=expCode;
    	this.extendInfo=formatMsg(msg, args);
    }
    
    /**
     * 实例化Elz异常
     * @param throwable 父异常
	 * @param sysName 系统名
     * @param expCode 异常代码
     */
    public ElzBaseException(Throwable throwable,String sysName,ElzExpCode expCode)
    {
    	super(formatExpMsg(sysName, expCode,""), throwable);
    	this.sysName=sysName;
    	this.expCode=expCode;
    }
    
    
    /**
     * 获取最底部的异常
     * @param claxx 需要获取的异常类型
     * @return 结果异常
     */
    public Throwable getBottomExpByType(final Class<? extends Throwable> claxx){
    	return ElzExceptionUtil.getBottomExpByType(this, claxx);
    }
    
    /**
     * 获取栈顶的Throwable
     * @param claxx 异常类型
     * @return 单个异常
     */
    public Throwable getTopElzExp(final Class<? extends Throwable> claxx){
    	return ElzExceptionUtil.getTopElzExp(this, claxx);
    }
    
    
    /**
     * 通过异常代码获取异常列表
     * @param expCode 异常代码
     * @return 异常列表
     */
    public List<ElzBaseException> getExpListByCode(final ElzExpCode expCode){
    	return ElzExceptionUtil.getExpListByCode(this, expCode);
    }
    
    /**
     * 通过异常代码数组获取异常列表
     * @param expCodeArr 异常代码数组
     * @return 异常列表
     */
    public List<ElzBaseException> getExpListByCode(final ElzExpCode [] expCodeArr){
    	return ElzExceptionUtil.getExpListByCode(this, expCodeArr);
    }
    
    /**
     * 获取栈底的ElzBaseException
     * @return 单个异常
     */
    public ElzBaseException getBottomElzExp(){
    	return ElzExceptionUtil.getBottomElzExp(this);
    }
    
    /**
     * 获取异常信息列表
     * @return 异常信息列表
     */
    public List<String> getExpMsgList(){
    	return ElzExceptionUtil.getExpMsgList(this);
    }
    
    
    /**
     * 通过异常代码获取单个异常
     * 如果有多个相同代码的异常，则只默认获取一个
     * @param expCode 异常代码
     * @return 单个异常
     */
    public ElzBaseException getExpByCode(final ElzExpCode expCode){
    	return ElzExceptionUtil.getExpByCode(this, expCode);
    }
    
    
    /**
     * 格式化消息
     * @param msg 消息
     * @param args 参数
     * @return 消息字符串
     */
    private static String formatMsg(String msg,Object ... args){
    	if(DataDetUtils.isStrEmpty(msg) || DataDetUtils.isArrEmpty(args)){
    		return msg;
    	}
    	return String.format(msg, args);
    }
    
    /**
     * 格式化异常信息
     * @param sysName 系统名
     * @param expCode 异常代码
     * @param msg 异常信息
     * @return 格式化后的异常信息
     */
	private static String formatExpMsg(String sysName,ElzExpCode expCode,String msg){
		String outMsg=sysName+"-"+expCode.getExpCode()+":"+expCode.getExpCodeDesp();
		if(!DataDetUtils.isStrEmpty(expCode.getResolveExp())){
			outMsg+="["+expCode.getResolveExp()+"]";
		}
		if(!DataDetUtils.isStrEmpty(msg)){
			outMsg+=":"+msg;
		}
		return outMsg;
	}
	
    
	public String getSysName() {
		return sysName;
	}

	public void setSysName(String sysName) {
		this.sysName = sysName;
	}

	public ElzExpCode getExpCode() {
		return expCode;
	}

	public void setExpCode(ElzExpCode expCode) {
		this.expCode = expCode;
	}
	
	/**
	 * 获取异常发生时间
	 * @return 发生时间
	 */
	public Date getOccurredTime() {
		return occurredTime;
	}

	public String getExtendInfo() {
		return extendInfo;
	}

	public void setExtendInfo(String extendInfo) {
		this.extendInfo = extendInfo;
	}
}
